package com.example.viewpager

import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import android.widget.OverScroller
import android.view.ViewConfiguration
import android.view.VelocityTracker
import android.view.MotionEvent

class MyViewPager(context: Context?, attrs: AttributeSet?) : ViewGroup(context, attrs) {
    private var downX = 0f
    private var downY = 0f
    private var downScrollY = 0f
    private var scrolling = false
    private val minVelocity: Float
    private val maxVelocity: Float
    private var trackingPointerId = 0
    private val overScroller: OverScroller
    private val viewConfiguration: ViewConfiguration
    private val velocityTracker = VelocityTracker.obtain()
    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)
    }

    override fun onLayout(changed: Boolean, l: Int, t: Int, r: Int, b: Int) {
        val childLeft = 0
        var childTop = 0
        val childRight = width
        var childBottom = height
        for (i in 0 until childCount) {
            val child = getChildAt(i)
            child.layout(childLeft, childTop, childRight, childBottom)
            childTop += height
            childBottom += height
        }
    }

    override fun onInterceptTouchEvent(ev: MotionEvent): Boolean {
        if (ev.actionMasked == MotionEvent.ACTION_DOWN) {
            velocityTracker.clear()
        }
        velocityTracker.addMovement(ev)
        var result = false
        when (ev.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                scrolling = false
                overScroller.abortAnimation()
                initCurrentPointerParam(ev, ev.actionIndex)
            }
            MotionEvent.ACTION_MOVE -> {
                val dx = downX - ev.x
                if (!scrolling) {
                    if (Math.abs(dx) > viewConfiguration.scaledPagingTouchSlop) {
                        scrolling = true
                        parent.requestDisallowInterceptTouchEvent(true)
                        result = true
                    }
                }
            }
        }
        return result
    }

    override fun onTouchEvent(ev: MotionEvent): Boolean {
        if (ev.actionMasked == MotionEvent.ACTION_DOWN) {
            velocityTracker.clear()
        }
        velocityTracker.addMovement(ev)
        when (ev.actionMasked) {
            MotionEvent.ACTION_DOWN -> {
                overScroller.abortAnimation()
                initCurrentPointerParam(ev, ev.actionIndex)
            }
            MotionEvent.ACTION_MOVE -> {
                val index = ev.findPointerIndex(trackingPointerId)
                var dy = downY - ev.getY(index) + downScrollY
                if (dy > height) {
                    dy = height.toFloat()
                } else if (dy < 0) {
                    dy = 0f
                }
                scrollTo(0, dy.toInt())
            }
            MotionEvent.ACTION_UP -> {
                // velocityTracker主要用来判断速度是否足以触发翻页
                velocityTracker.computeCurrentVelocity(1000, maxVelocity)
                val vy = velocityTracker.yVelocity
                val scrollY = scrollY
                val targetPage: Int = if (Math.abs(vy) < minVelocity) {
                    if (scrollY > height / 2) 1 else 0
                } else {
                    if (vy < 0) 1 else 0
                }
                val scrollDistance = if (targetPage == 1) height - scrollY else - scrollY
                overScroller.startScroll(0, getScrollY(), 0, scrollDistance, 500)
                postInvalidateOnAnimation()
            }
            MotionEvent.ACTION_POINTER_DOWN -> initCurrentPointerParam(ev, ev.actionIndex)
            MotionEvent.ACTION_POINTER_UP -> {
                val currentActionIndex = ev.actionIndex
                val pointerId = ev.getPointerId(currentActionIndex)
                if (pointerId == trackingPointerId) {
                    // 判断当前pointer是否最后一个
                    // 若是最后一个，则新的响应手势的手指index取值为PointerCount - 2
                    // 若不是最后一个，则新的响应手势的手指index取值为PointerCount - 1
                    initCurrentPointerParam(
                        ev,
                        ev.pointerCount - if (currentActionIndex == ev.pointerCount - 1) 2 else 1
                    )
                }
            }
        }
        return true
    }

    // 初始化当前响应事件的pointer信息
    private fun initCurrentPointerParam(ev: MotionEvent, actionIndex: Int) {
        trackingPointerId = ev.getPointerId(actionIndex)
        downX = ev.getX(actionIndex)
        downY = ev.getY(actionIndex)
        downScrollY = scrollY.toFloat()
    }

    override fun computeScroll() {
        if (overScroller.computeScrollOffset()) {
            scrollTo(overScroller.currX, overScroller.currY)
            postInvalidateOnAnimation()
        }
    }

    init {
        overScroller = OverScroller(context)
        viewConfiguration = ViewConfiguration.get(context)
        maxVelocity = viewConfiguration.scaledMaximumFlingVelocity.toFloat()
        minVelocity = viewConfiguration.scaledMinimumFlingVelocity.toFloat()
    }
}